//-------------------------------------------------------------------
//	Copyright (c) 2010-2012 Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#ifndef _UX_CAMERA_COMPONENT_H
#define _UX_CAMERA_COMPONENT_H

#include "../SceneMessages.h"
#include "../SceneTypes.h"

namespace Engine
{
namespace Scene
{

	//
	// Camera Component
	//

	class _EXPORT_ CCameraComp : public IBaseSNComponent,
								 public ICameraObject,
								 public CViewport
	{
	protected:
		camera_t		_sCamera;
		e_camera::type	_eCamType;
		uint8			_uMaxLOD;

	private:
		static const string	_s_sCameraCompTypeName;

	public:
		CCameraComp();
		~CCameraComp();
		

		// ISNComponent //
		virtual void Free();
		virtual bool ProcessMessage(TSNCompMessage &);
		virtual bool GetMetaIterator(CMetaSetIterator *&);
		
		virtual const string &		GetTypeName() const;
		virtual e_component::type	GetComponentBits() const;


		// CViewport //
		virtual bool Bind();
		virtual bool Unbind();


		// ICameraObject //
		virtual void GetParameters(const mat4 **pView, const mat4 **pProj,
									const frustum_t **pFrustum,
									vec3 *pRotation, vec3 *pPosition,
									vec2 *pClipPlanes, uint8 *pMaxLOD);

		virtual CViewport *		GetViewport();
		virtual e_camera::type	GetCameraType() const;


		// CEngBaseObject //
		virtual void Release();
	};



	//
	// Input Camera Component
	//

	class _EXPORT_ CInputCameraComp : public CCameraComp
	{
	public:
		// types
		enum ECameraType
		{
			CT_UNKNOWN		= 0,
			CT_FPS,
			CT_FREE_FPS,
			CT_FLIGHT,
		};

		enum ECameraAction
		{
			CA_UNKNOWN		= 0,
			CA_MOVE_FORWARD,		// W
			CA_MOVE_BACKWARD,		// S
			CA_MOVE_LEFT,			// A
			CA_MOVE_RIGHT,			// D
			CA_MOVE_UP,				// SPACE
			CA_MOVE_DOWN,			// SHIFT
			CA_INCREASE,			// Mouse Wheel Up
			CA_DECREASE,			// Mouse Wheel Down
			CA_ROLL_POS,
			CA_ROLL_NEG,
			CA_YAW_POS,
			CA_YAW_NEG,
			CA_PITCH_POS,
			CA_PITCH_NEG,
		};

		typedef TKeyBind< ECameraAction >		TCameraKeyBind;
		typedef array< TCameraKeyBind >			key_bind_array_t;
		typedef void (CInputCameraComp:: *PActionProc_t)(int8);

		struct TKeyAction
		{
			PActionProc_t	pProc;
			TCameraKeyBind	sBind;
			int8			iParam;
			///
			TKeyAction():
				pProc(nullptr), iParam(0) {}

			TKeyAction(PActionProc_t proc, int8 param, ECameraAction act, e_key::type key):
				pProc(proc), sBind(act, key), iParam(param) {}
		};

		typedef array< TKeyAction >		actions_array_t;
		typedef void (CInputCameraComp:: *PUpdateProc_t)();

	protected:
		PUpdateProc_t		_pUpdate;
		actions_array_t		_aActions;
		vec3				_vTempMove,
							_vTempRot;
		vec3				_vAxisSens;		// rotation axis sensitivity
		float				_fVelocity,
							_fMouseSens;
		float				_fDist;			// distance betwen screen and user eyes
		e_vec_swizzle::type	_eRotSwizzle;
		
	protected:
		void _MoveForward(int8);
		void _MoveLeft(int8);
		void _MoveUp(int8);
		void _Increase(int8);
		void _Roll(int8);
		void _Yaw(int8);
		void _Pitch(int8);

		void _Update(float fTime);
		
		void _UpdateFPS();
		void _UpdateFreeFPS();
		void _UpdateFlight();

	public:
		CInputCameraComp();
		~CInputCameraComp();
		

		void Create(const vec3 &vPos, const vec3 &vRot, const vec2 &vClip, const irect &sView, float fFovY, float fAspect);
		void OnResize(const irect &sView, float fFovY, float fAspect);

		void Create(const vec3 &vPos, const vec3 &vRot, const vec2 &vClip, const irect &sView, float fDist);
		void OnResize(const irect &sView);

		void Create(const vec3 &vPos, const vec3 &vRot, const vec2 &vClip, float fDist);

		void SetType(ECameraType eType);
		void SetSens(float fMouseSens, const vec3 &vAxisSens, float fVelocity, e_vec_swizzle::type eRotSw);
		void SetKeyBinds(const key_bind_array_t &);
		

		virtual void OnResize();
		virtual bool ProcessMessage(TSNCompMessage &);
	};

//-------------------------------------------------------------------

}	// Scene
}	// Engine

#endif	// _UX_CAMERA_COMPONENT_H